home *** CD-ROM | disk | FTP | other *** search
- //////////////////////////////////
- // VECTOR BALLS 2 //
- // (c) 1994 by Bodies In Motion //
- // code - Tumblin //
- // graphics - Rush //
- //////////////////////////////////
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <conio.h>
- #include <dos.h>
- #include <xlib_all.h>
-
- // include the palette and bitmap data of the vector ball
- #include "vectbal2.h"
-
- //──────────────────────── fixed point math code ─────────────────────────
-
- typedef long Fixedpoint;
-
- #define Int2Fixed(a) (Fixedpoint)((Fixedpoint)(a) << 16)
- #define Fixed2Int(a) (int)((a) >> 16)
- #define Float2Fixed(a) ((Fixedpoint)((a) * 65536.0))
- #define Fixed2Float(a) ((a) / 65536.0)
-
- extern "C" {
- Fixedpoint FixedMul(Fixedpoint,Fixedpoint);
- Fixedpoint FixedDiv(Fixedpoint,Fixedpoint);
- };
-
-
- //──────────────────────── some helpful constants ────────────────────────
-
- // maximum # of degrees for sin and cos tables
- #define MAXDEGREES 720
-
- // distance from users eye to screen surface in pixels
- #define EYE_DISTANCE Int2Fixed(256)
-
- // depth to push objects into the screen
- #define DEPTH Int2Fixed(1024)
-
- // maximum number of balls an object can have
- #define MAXBALLS 100
-
- //──────────────────────────── data structures ───────────────────────────
- //────────────────────────────────────────────────────────────────────────
-
- char filename[80];
-
- Fixedpoint cosine[MAXDEGREES]; // cosine lookup table
- Fixedpoint sine[MAXDEGREES]; // sine lookup table
-
- typedef struct
- {
- Fixedpoint ox,oy,oz; // origional x,y,z coordinates of ball
- Fixedpoint wx,wy,wz; // working copy of x,y,z coordinates of ball
- int sx,sy,sz; // screen coordinates of ball
- } BallTYPE;
-
- int NumOfBalls=0; // current number of defined balls in object
-
- BallTYPE Ball[MAXBALLS]; // object containing MAXBALLS balls
- int SBall[MAXBALLS]; // indexes to ball structures (for qsorting)
-
- int XAngle=0; // degrees to rotate object around x axis
- int YAngle=0; // degrees to rotate object around y axis
- int ZAngle=0; // degrees to rotate object around z axis
-
- // bounding erase box
- int EraseLeft; // current frame
- int EraseTop; // current frame
- int EraseRight; // current frame
- int EraseBottom; // current frame
- int EraseLeft1; // from 1 frame ago
- int EraseTop1; // from 1 frame ago
- int EraseRight1; // from 1 frame ago
- int EraseBottom1; // from 1 frame ago
- int EraseLeft2; // from 2 frames ago
- int EraseTop2; // from 2 frames ago
- int EraseRight2; // from 2 frames ago
- int EraseBottom2; // from 2 frames ago
-
- unsigned char old_palette[768];
- unsigned char current_palette[768]={0};
-
- //───────────────────────────── function prototypes ────────────────────────
-
- void main(int argc,char *argv[]);
- void InitSinCosTables(void);
- void InitSortList(void);
- int LoadObject(char * filename);
- void UpdateBalls(void);
- int CompareBalls(const void *a, const void *b);
- void WaitVerticalRetrace(void);
- void FadeInPalette(unsigned char *,int);
- void FadeOutPalette(int);
- void GetPalette(unsigned char *);
- void SetPalette(unsigned char *);
- void FadeInOne64th(unsigned char *,unsigned char *);
- void FadeOutOne64th(unsigned char *);
-
- //──────────────── code to create sin and cos lookup tables ──────────────
-
- void InitSinCosTables(void)
- {
- int i;
- for(i=0; i<MAXDEGREES; i++)
- {
- cosine[i]=Float2Fixed(cos((float)i*360/MAXDEGREES * 3.14159265 / 180.0));
- sine[i] =Float2Fixed(sin((float)i*360/MAXDEGREES * 3.14159265 / 180.0));
- }
- }
-
- //──────────────────── initialize the sorted ball list ──────────────────────
-
- void InitSortList(void)
- {
- // point each element to an initial ball
- for(int i=0; i<MAXBALLS; i++)
- {
- SBall[i]=i;
- }
- }
-
- //────────────────────────── compare balls (for qsort) ─────────────────────
-
- int CompareBalls(const void *a, const void *b)
- {
- if( Ball[*(int *)a].sz < Ball[*(int *)b].sz )
- {
- return -1;
- }
- else if( Ball[*(int *)a].sz > Ball[*(int *)b].sz )
- {
- return +1;
- }
- else
- {
- return 0;
- }
- }
-
- //──────────────────────── update vector ball object ─────────────────────
-
- void UpdateBalls(void)
- {
- int i;
- Fixedpoint nx,ny,nz;
- Fixedpoint sinxangle,cosxangle;
- Fixedpoint sinyangle,cosyangle;
- Fixedpoint sinzangle,coszangle;
-
- // initialize the bounding box to its extremes
- EraseLeft=320;
- EraseTop=240;
- EraseRight=0;
- EraseBottom=0;
-
- // get the sine and cosine angles to save time from table lookup
- sinxangle=sine[XAngle];
- cosxangle=cosine[XAngle];
- sinyangle=sine[YAngle];
- cosyangle=cosine[YAngle];
- sinzangle=sine[ZAngle];
- coszangle=cosine[ZAngle];
-
- // rotate the balls
- for(i=0;i<NumOfBalls;i++)
- {
- // rotate around the x-axis
- Ball[i].wz=FixedMul(Ball[i].oy,cosxangle) - FixedMul(Ball[i].oz,sinxangle);
- Ball[i].wy=FixedMul(Ball[i].oy,sinxangle) + FixedMul(Ball[i].oz,cosxangle);
- Ball[i].wx=Ball[i].ox;
-
- // rotate around the y-axis
- nx=FixedMul(Ball[i].wx,cosyangle) - FixedMul(Ball[i].wz,sinyangle);
- nz=FixedMul(Ball[i].wx,sinyangle) + FixedMul(Ball[i].wz,cosyangle);
- Ball[i].wx=nx;
- Ball[i].wz=nz;
-
- // rotate around the z-axis
- nx=FixedMul(Ball[i].wx,coszangle) - FixedMul(Ball[i].wy,sinzangle);
- ny=FixedMul(Ball[i].wx,sinzangle) + FixedMul(Ball[i].wy,coszangle);
- Ball[i].wx=nx;
- Ball[i].wy=ny;
-
- // project the 3-D coordinates to screen coordinates
- Ball[i].sx=Fixed2Int(FixedMul(FixedDiv(Ball[i].wx,Ball[i].wz - DEPTH),EYE_DISTANCE)) + 160;
- Ball[i].sy=Fixed2Int(FixedMul(FixedDiv(Ball[i].wy,Ball[i].wz - DEPTH),EYE_DISTANCE)) + 120;
- Ball[i].sz=Fixed2Int(Ball[i].wz-DEPTH);
-
- // and while we're at it, find the bounding box for erasing balls
- if(Ball[i].sx < EraseLeft)
- {
- EraseLeft=Ball[i].sx;
- }
- if(Ball[i].sy < EraseTop)
- {
- EraseTop=Ball[i].sy;
- }
- if(Ball[i].sx > EraseRight)
- {
- EraseRight=Ball[i].sx;
- }
- if(Ball[i].sy > EraseBottom)
- {
- EraseBottom=Ball[i].sy;
- }
- }
-
- // sort the balls according to their z coordinate
- qsort((const void *)SBall,NumOfBalls,sizeof(SBall[0]),CompareBalls);
-
- // erase the balls from 2 frames ago (remember, we're double buffering)
- x_rect_fill(EraseLeft2-12,EraseTop2-12,
- EraseRight2+16,EraseBottom2+16,
- HiddenPageOffs,0);
-
- // draw the new balls onto the screen
- for(i=0; i<NumOfBalls; i++)
- {
- x_put_masked_pbm(Ball[SBall[i]].sx-12,Ball[SBall[i]].sy-12,
- HiddenPageOffs,bitmap);
- }
-
- // update the bounding boxes for this frame
- EraseTop2=EraseTop1;
- EraseLeft2=EraseLeft1;
- EraseRight2=EraseRight1;
- EraseBottom2=EraseBottom1;
- EraseTop1=EraseTop;
- EraseLeft1=EraseLeft;
- EraseRight1=EraseRight;
- EraseBottom1=EraseBottom;
- }
-
- //────────── load a dot object for use as a vector ball object ───────────
-
- int LoadObject(char *filename)
- {
- int i,temp;
- FILE *file;
-
- // open the file to read from it
- if ((file = fopen(filename,"rb")) == NULL)
- {
- printf("\n\nCannot open input file.\n");
- return (0);
- }
- else
- {
- // okay file is ready to read data from it
-
- // read number of dots in file
- fread(&NumOfBalls,sizeof(int),1,file);
-
- // read in all of the object's dots
- for(i=0;i < NumOfBalls; i++)
- {
- fread(&temp,sizeof(int),1,file);
- Ball[i].ox=Int2Fixed(temp);
- fread(&temp,sizeof(int),1,file);
- Ball[i].oy=Int2Fixed(temp);
- fread(&temp,sizeof(int),1,file);
- Ball[i].oz=Int2Fixed(temp);
- }
-
- // we're finished, close the file
- fclose(file);
- return (1);
- }
- }
-
- //──────────────────────── palette fading code ───────────────────────────
-
- void WaitVerticalRetrace(void)
- {
- asm mov dx,3dah
-
- top_of_retrace:
- asm in al,dx
- asm and al,08h
- asm jnz top_of_retrace
-
- bottom_of_retrace:
- asm in al,dx
- asm and al,08h
- asm jz bottom_of_retrace
- }
-
- void GetPalette(unsigned char *palettebuffer)
- {
- int i;
-
- for(i=0;i<256;i++)
- {
- outp(0x3c7,i); // color number to get data from
- palettebuffer[i*3] = inp(0x3c9); // red
- palettebuffer[i*3+1] = inp(0x3c9); // green
- palettebuffer[i*3+2] = inp(0x3c9); // blue
- }
- }
-
- void SetPalette(unsigned char *palettebuffer)
- {
- int i;
-
- for(i=0;i<256;i++)
- {
- outp(0x3c8,i); // color number to set
- outp(0x3c9,palettebuffer[i*3]); // red
- outp(0x3c9,palettebuffer[i*3+1]); // green
- outp(0x3c9,palettebuffer[i*3+2]); // blue
- }
- }
-
- void FadeInPalette(unsigned char *palettebuffer,int speed)
- {
- int i,j,k;
- unsigned char temppalette[768]={0};
-
- for(i=0;i<64;i++)
- {
- for(j=0;j<256;j++)
- {
- // do the red component
- if(temppalette[j*3] < palettebuffer[j*3])
- {
- temppalette[j*3]++;
- }
- // do the green component
- if(temppalette[j*3+1] < palettebuffer[j*3+1])
- {
- temppalette[j*3+1]++;
- }
- // do the blue component
- if(temppalette[j*3+2] < palettebuffer[j*3+2])
- {
- temppalette[j*3+2]++;
- }
- }
- for(k=0;k<speed;k++)
- {
- WaitVerticalRetrace();
- }
- SetPalette(temppalette);
- }
- }
-
- void FadeOutPalette(int speed)
- {
- int i,j,k;
- unsigned char temppalette[768];
-
- GetPalette(temppalette);
-
- for(i=0;i<64;i++)
- {
- for(j=0;j<256;j++)
- {
- // do the red component
- if(temppalette[j*3] > 0)
- {
- temppalette[j*3]--;
- }
- // do the green component
- if(temppalette[j*3+1] > 0)
- {
- temppalette[j*3+1]--;
- }
- // do the blue component
- if(temppalette[j*3+2] > 0)
- {
- temppalette[j*3+2]--;
- }
- }
- for(k=0;k<speed;k++)
- {
- WaitVerticalRetrace();
- }
- SetPalette(temppalette);
- }
- }
-
- //───────────────────────────── main program ─────────────────────────────
-
- void main(int argc,char *argv[])
- {
-
- if(argc<=1)
- {
- printf("┌─────────────────┐\n");
- printf("│ VECTOR BALLS II │\n");
- printf("└─────────────────┘\n");
- printf("Syntax: VECTBAL2 filename.DOT\n\n");
- exit(1);
- }
-
- if(LoadObject(argv[1])==0)
- {
- printf("Error: could not find that file.\n");
- exit(1);
- }
-
-
- InitSinCosTables();
- InitSortList();
- GetPalette(old_palette);
-
- SetPalette(current_palette);
- _setcursortype(_NOCURSOR);
- clrscr();
- printf("\n\n\n\n\n\n\n\n");
- printf(" ┌──────────────────────────────┐\n");
- printf(" │ VECTOR BALLS II │\n");
- printf(" │ (c) 1994 by Bodies In Motion │\n");
- printf(" │ code - Tumblin │\n");
- printf(" │ graphics - Rush │\n");
- printf(" └──────────────────────────────┘\n\n\n");
-
- FadeInPalette(old_palette,2);
- delay(1000);
- FadeOutPalette(2);
-
- x_set_mode(X_MODE_320x240,320);
- x_set_doublebuffer(240);
- x_put_pal_raw(palette,256,0);
- delay(1000);
-
- do
- {
- XAngle+=6;
- if(XAngle >= MAXDEGREES)
- {
- XAngle -= MAXDEGREES;
- }
- YAngle+=4;
- if(YAngle >= MAXDEGREES)
- {
- YAngle -= MAXDEGREES;
- }
- ZAngle+=3;
- if(ZAngle >= MAXDEGREES)
- {
- ZAngle -= MAXDEGREES;
- }
-
- UpdateBalls();
- x_page_flip(0,0);
- } while(!kbhit());
-
- getch();
-
- x_text_mode();
- for(int i=0;i<256;i++)
- {
- current_palette[i]=0;
- }
- SetPalette(current_palette);
- printf("We hope this has been a 'moving' experience.");
- delay(1000);
- FadeInPalette(old_palette,1);
- _setcursortype(_NORMALCURSOR);
- }
-